package lesson

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"server/internal/dao"
	"server/internal/model"
	"server/internal/model/do"
	"server/internal/model/entity"
	"server/internal/service"
)

type sLessonCategory struct {
}

func init() {
	service.RegisterLessonCategory(&sLessonCategory{})
}

func (s *sLessonCategory) Create(ctx context.Context, in model.LessonCategoryCreateInput) (id int64, err error) {
	if err = s.checkCodeIsRepeat(ctx, in.Code, 0); err != nil {
		return 0, err
	}
	id, err = dao.LessonCategory.Ctx(ctx).Data(do.LessonCategory{
		ParentId:  in.ParentId,
		Name:      in.Name,
		Code:      in.Code,
		Cover:     in.Cover,
		Remark:    in.Remark,
		CreatedBy: service.SystemLogin().GetAdminID(ctx),
	}).InsertAndGetId()
	if err != nil {
		return 0, err
	}
	return id, nil
}

func (s *sLessonCategory) GetOneByID(ctx context.Context, id int64) (data *entity.LessonCategory, err error) {
	data = new(entity.LessonCategory)
	err = dao.LessonCategory.Ctx(ctx).Where(do.LessonCategory{Id: id}).Scan(data)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (s *sLessonCategory) UpdateByID(ctx context.Context, id int64, in model.LessonCategoryUpdateInput) (rows int64, err error) {
	if err = s.checkCodeIsRepeat(ctx, in.Code, id); err != nil {
		return 0, err
	}
	rows, err = dao.LessonCategory.Ctx(ctx).Where(do.LessonCategory{Id: id}).Data(do.LessonCategory{
		ParentId:  in.ParentId,
		Name:      in.Name,
		Code:      in.Code,
		Cover:     in.Cover,
		Remark:    in.Remark,
		UpdatedBy: service.SystemLogin().GetAdminID(ctx),
	}).UpdateAndGetAffected()
	if err != nil {
		return 0, err
	}
	return rows, nil
}

func (s *sLessonCategory) checkCodeIsRepeat(ctx context.Context, code string, id int64) error {
	where := g.Map{
		"code": code,
	}
	if id > 0 {
		where["id <> ?"] = id
	}
	count, err := dao.LessonCategory.Ctx(ctx).Where(where).Count()
	if err != nil {
		return err
	}
	if count > 0 {
		return gerror.New("code 重复")
	}
	return nil
}

func (s *sLessonCategory) DeleteByID(ctx context.Context, id int64) (rows int64, err error) {
	rows, err = dao.LessonCategory.Ctx(ctx).Where(do.LessonCategory{Id: id}).Data(do.LessonCategory{
		DeletedAt: gtime.Now(),
		DeletedBy: service.SystemLogin().GetAdminID(ctx),
	}).UpdateAndGetAffected()
	if err != nil {
		return 0, err
	}
	return rows, nil
}

func (s *sLessonCategory) List(ctx context.Context) (list []model.LessonCategoryListItem, err error) {
	list = make([]model.LessonCategoryListItem, 0)
	err = dao.LessonCategory.Ctx(ctx).OrderAsc("id").Scan(&list)
	if err != nil {
		return
	}

	// 创建人
	err = dao.SystemUser.Ctx(ctx).As("u").Fields("u.*").
		WhereIn("u.id", gdb.ListItemValuesUnique(list, "CreatedBy")).
		ScanList(&list, "CreatedAdmin", "id:created_by")
	if err != nil {
		return
	}

	// 更新人
	err = dao.SystemUser.Ctx(ctx).As("u").Fields("u.*").
		WhereIn("u.id", gdb.ListItemValuesUnique(list, "UpdatedBy")).
		ScanList(&list, "UpdatedAdmin", "id:updated_by")
	if err != nil {
		return
	}

	return s.listToTree(list, 0), nil
}
func (s *sLessonCategory) listToTree(items []model.LessonCategoryListItem, parentId uint64) []model.LessonCategoryListItem {
	tree := make([]model.LessonCategoryListItem, 0)
	for _, item := range items {
		if item.ParentId == parentId {
			item.Children = s.listToTree(items, item.Id)
			tree = append(tree, item)
		}
	}
	return tree
}
